package com.icongyou.enterprise.talent_pool.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.icongyou.enterprise.data_aggregation.entity.AssignmentEntity;
import com.icongyou.enterprise.data_aggregation.service.DataAggregationService;
import com.icongyou.enterprise.talent_pool.entity.StudentAssignmentPerformanceEntity;
import com.icongyou.enterprise.talent_pool.entity.vo.StudentSubmissionInfo;
import com.icongyou.enterprise.talent_pool.mapper.StudentAssignmentPerformanceMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class StudentAssignmentPerformanceServiceImplTest {

    @Mock
    private StudentAssignmentPerformanceMapper studentAssignmentPerformanceMapper;

    @Mock
    private DataAggregationService dataAggregationService;

    @InjectMocks
    private StudentAssignmentPerformanceServiceImpl studentAssignmentPerformanceService;

    private AssignmentEntity assignment;
    private StudentSubmissionInfo submissionInfo;
    private final String assignmentId = "test-assignment-123";
    private final String studentId = "student-123";
    private final String teamId = "team-123";

    @BeforeEach
    void setUp() {
        // 初始化测试数据
        assignment = new AssignmentEntity();
        assignment.setAssignmentId(assignmentId);
        assignment.setAssignmentType(0); // 个人任务
        assignment.setFullScore(BigDecimal.valueOf(100.0));

        submissionInfo = new StudentSubmissionInfo();
        submissionInfo.setSubmissionId("submission-123");
        submissionInfo.setStudentId(studentId);
        submissionInfo.setTeamId(teamId);
        submissionInfo.setSubmissionTime(LocalDateTime.now());
        submissionInfo.setFinalScore(85.0);
        submissionInfo.setIsLate(0);
        submissionInfo.setIsTeacherRecommended(1);
        submissionInfo.setLikeCount(10);
        submissionInfo.setFavoriteCount(5);
        submissionInfo.setAssignmentType(0);
    }

    @Test
    void calculateStudentAssignmentPerformanceIncrementally_ShouldProcessAssignments() {
        // 准备数据
        List<String> assignmentIds = Arrays.asList("assign-1", "assign-2");
        when(studentAssignmentPerformanceMapper.getAssignmentsToCalculate(any(LocalDateTime.class)))
                .thenReturn(assignmentIds);
        when(dataAggregationService.getAssignmentInfo(anyString())).thenReturn(assignment);
        when(studentAssignmentPerformanceMapper.getAssignmentSubmissions(anyString()))
                .thenReturn(Collections.singletonList(submissionInfo));

        // 执行方法
        studentAssignmentPerformanceService.calculateStudentAssignmentPerformanceIncrementally();

        // 验证
        verify(studentAssignmentPerformanceMapper, times(1)).getAssignmentsToCalculate(any(LocalDateTime.class));
        verify(dataAggregationService, times(2)).getAssignmentInfo(anyString());
    }

    @Test
    void calculateStudentAssignmentPerformanceIncrementally_WithEmptyAssignmentIds_ShouldReturnEarly() {
        // 准备数据
        when(studentAssignmentPerformanceMapper.getAssignmentsToCalculate(any(LocalDateTime.class)))
                .thenReturn(Collections.emptyList());

        // 执行方法
        studentAssignmentPerformanceService.calculateStudentAssignmentPerformanceIncrementally();

        // 验证
        verify(studentAssignmentPerformanceMapper, times(1)).getAssignmentsToCalculate(any(LocalDateTime.class));
        verify(dataAggregationService, never()).getAssignmentInfo(anyString());
    }

    @Test
    void calculateAssignmentPerformanceRealtime_WithPersonalAssignment_ShouldReturnPerformance() throws JsonProcessingException {
        // 准备数据
        when(dataAggregationService.getAssignmentInfo(assignmentId)).thenReturn(assignment);
        when(studentAssignmentPerformanceMapper.getAssignmentSubmissions(assignmentId))
                .thenReturn(Collections.singletonList(submissionInfo));

        // 执行方法
        List<StudentAssignmentPerformanceEntity> result =
                studentAssignmentPerformanceService.calculateAssignmentPerformanceRealtime(assignmentId);

        // 验证
        assertNotNull(result);
        assertFalse(result.isEmpty());
        assertEquals(1, result.size());

        StudentAssignmentPerformanceEntity performance = result.get(0);
        assertEquals(studentId, performance.getStudentId());
        assertEquals(assignmentId, performance.getAssignmentId());
        assertNotNull(performance.getPerformanceScore());
        assertTrue(performance.getPerformanceScore() > 0);
    }

    @Test
    void calculateAssignmentPerformanceRealtime_WithTeamAssignment_ShouldReturnPerformance() throws JsonProcessingException {
        // 准备数据 - 团队任务
        assignment.setAssignmentType(1); // 团队任务
        String contributionRateJson = "[{\"studentId\":\"student-123\",\"rate\":60.0},{\"studentId\":\"student-456\",\"rate\":40.0}]";

        submissionInfo.setAssignmentType(1);
        submissionInfo.setContributionRate(contributionRateJson);

        when(dataAggregationService.getAssignmentInfo(assignmentId)).thenReturn(assignment);
        when(studentAssignmentPerformanceMapper.getAssignmentSubmissions(assignmentId))
                .thenReturn(Collections.singletonList(submissionInfo));
        when(studentAssignmentPerformanceMapper.getTeamStudentIds(teamId))
                .thenReturn(Arrays.asList("student-123", "student-456"));
        when(studentAssignmentPerformanceMapper.getTeamAverageContribution(eq(assignmentId), eq(teamId)))
                .thenReturn(50.0);

        // 执行方法
        List<StudentAssignmentPerformanceEntity> result =
                studentAssignmentPerformanceService.calculateAssignmentPerformanceRealtime(assignmentId);

        // 验证
        assertNotNull(result);
        assertEquals(2, result.size()); // 两个团队成员
    }

    @Test
    void calculateAssignmentPerformanceRealtime_WithNullAssignment_ShouldReturnEmptyList() {
        // 准备数据
        when(dataAggregationService.getAssignmentInfo(assignmentId)).thenReturn(null);

        // 执行方法
        List<StudentAssignmentPerformanceEntity> result =
                studentAssignmentPerformanceService.calculateAssignmentPerformanceRealtime(assignmentId);

        // 验证
        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

    @Test
    void calculateAssignmentPerformanceRealtime_WithEmptySubmissions_ShouldReturnEmptyList() {
        // 准备数据
        when(dataAggregationService.getAssignmentInfo(assignmentId)).thenReturn(assignment);
        when(studentAssignmentPerformanceMapper.getAssignmentSubmissions(assignmentId))
                .thenReturn(Collections.emptyList());

        // 执行方法
        List<StudentAssignmentPerformanceEntity> result =
                studentAssignmentPerformanceService.calculateAssignmentPerformanceRealtime(assignmentId);

        // 验证
        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

    @Test
    void parseContributionRate_WithValidJson_ShouldReturnContributionRate() throws Exception {
        // 准备数据
        String contributionRateJson = "[{\"studentId\":\"student-123\",\"rate\":60.0},{\"studentId\":\"student-456\",\"rate\":40.0}]";

        // 使用反射直接调用私有方法
        Method method = StudentAssignmentPerformanceServiceImpl.class
                .getDeclaredMethod("parseContributionRate", String.class, String.class);
        method.setAccessible(true);

        Double result = (Double) method.invoke(studentAssignmentPerformanceService, contributionRateJson, "student-123");

        // 验证
        assertNotNull(result, "贡献率解析结果不应为null");
        assertEquals(60.0, result, 0.001, "贡献率应该正确解析");
    }

    @Test
    void calculateSingleStudentPerformance_WithPersonalAssignment_ShouldCalculateCorrectly() {
        // 准备数据
        submissionInfo.setFinalScore(85.0);
        assignment.setFullScore(BigDecimal.valueOf(100.0));

        // 使用反射调用私有方法
        try {
            java.lang.reflect.Method method = StudentAssignmentPerformanceServiceImpl.class
                    .getDeclaredMethod("calculateSingleStudentPerformance",
                            String.class, String.class, StudentSubmissionInfo.class, Integer.class, Double.class);
            method.setAccessible(true);

            Double result = (Double) method.invoke(studentAssignmentPerformanceService,
                    studentId, assignmentId, submissionInfo, 0, 100.0);

            // 验证
            assertNotNull(result);
            assertTrue(result >= 0 && result <= 100);
        } catch (Exception e) {
            fail("反射调用私有方法失败: " + e.getMessage());
        }
    }
}